/*
 * cryptObject.cpp
 *
 *  Created on: 21.03.2009
 *      Author: Christian Stupp
 */

#include "../include/cryptObject.h"

//void debug(std::string value) {
//	std::cout << value << std::endl;
//}

/**
 * Gets the type of the current crypt method
 *
 * @return	string	current setting type
 */
std::string oal::cryptObject::getType(void) {
	return this->_method;
}

/**
 * create a new instance of the cryptObject
 *
 * @param	string	method of encrypt (if empty rc4 is set)
 * @param	string	key for encryption, can be empty, than you must
 * 					set the key with the function setKey();
 */
oal::cryptObject::cryptObject(std::string method, std::string key) {
	this->_method = method;
	this->_md5Value = "";
//	debug->add("Start encryption with key " + key,__FILE__,__LINE__,10);
	if (!key.empty()) this->setKey(key);
}

/**
 * create a new instance of the cryptObject without key
 */
oal::cryptObject::~cryptObject() {
	// TODO Auto-generated destructor stub
}

/**
 * Puts the given source into the unsigned destionion
 *
 * @param	unsigned char*
 */
void oal::cryptObject::stringToChar(unsigned char *destination, std::string source) {
	for(int i=0;i < (int)source.length(); ++i) {
		destination[i] = source[i];
	}
}

/**
 * Sets the key for the crypt and uncrypt function
 *
 * @param	string	key for crypt
 */
void oal::cryptObject::setKey(std::string key) {
	debug->add("Set key " + key,__FILE__,__LINE__,10);
	this->_key = this->stringReplace("\r","",this->stringReplace("\n","",trim(key)));
}


/**
 * Sets the key for the crypt and uncrypt function and extract the
 * md5 value and sets it for future access in this class
 *
 * @param	string	complete rsa file with the md5
 * 					value in the first line, can
 * 					not be empty
 */
void oal::cryptObject::setRsaKey(std::string key) {
	int pos = key.find("\n");
	if(pos < 0) {
		std::cerr << "no linebreak found" << std::endl;
		exit(1);
	}
	this->_md5Value = trim(key.substr(0,pos+1));
	this->setKey(key.substr(pos));
}

/**
 * performs cryption of the given string. First you must use the function setKey
 * to set the key for encryption. The content will be crypted or decrypted. You
 *
 * @TODO	add more methods like rc4 (aes or so)
 *
 * @param	string	content to crypt
 *
 * @return	string	content encrypted or decrypted
 *
 */
std::string oal::cryptObject::performCryption(std::string content) {
	std::string result ="";
//	debug->add("performEncryption " + this->content.length(),__FILE__,__LINE__,10);

	if(this->_key.length() <= 0) {
		std::cerr << "Please use the function setKey first" << std::endl;
		exit(1);
	}
	unsigned char *key= (unsigned char*)malloc((this->_key.length()+1)* sizeof(unsigned char));
	unsigned char *buf1= (unsigned char*)malloc((content.length()+1)* sizeof(unsigned char));
	unsigned char *buf2= (unsigned char*)malloc((content.length()+1)* sizeof(unsigned char));

	// put string into unsigned char
	this->stringToChar(buf1, content);
	this->stringToChar(key, this->_key);

	// do crypt and uncrypt
	RC4_KEY KEY;
	RC4_set_key(&KEY,this->_key.length(),key);
	RC4(&KEY,content.length(),buf1,buf2);

	// put the content back to string
	for(int i=0;i<(int)content.length();++i) result.push_back(buf2[i]);

	free(key);
	free(buf1);
	free(buf2);

	return result;
}

/**
 * Returns the md5 value if sets with the function setRsaKey()
 *
 * @return	string	md5 value of the rsa key,
 * 					can be empty if no key is set
 */
std::string oal::cryptObject::getMd5ToAuthentificate(void) {
	if(this->_key.length() <= 0 || this->_md5Value.length() <= 0) {
		std::cerr << "Please use the function setRsaKey first" << std::endl;
		exit(1);
	}
	return	this->_md5Value;
}

/**
 * Returns an md5 converted string
 *
 * @param	string	text to make md5 value
 *
 * @param	string	md5 for text
 */
std::string oal::cryptObject::md5(std::string data) {
	string result ="";
	MD5_CTX context;
	int i;
	unsigned char digest[16];
	unsigned int len = data.length();

	MD5_Init(&context);
	MD5_Update (&context, data.c_str(), len);
	MD5_Final(digest, &context);

	for (i = 0; i < 16; i++) {
		char buffer[2];
		sprintf (buffer, "%02x", digest[i]);
		result.append(buffer);
	}

	return result;
}




